#include <iostream>
#include <set>
#include <vector>
using namespace std;

int main() {
    // 读取顶点数量
    int n;
    cin >> n;
    
    // parent数组存储每个节点的父节点（编号）
    vector<int> parent(100005);
    // respect数组记录每个节点是否尊重其父节点：1表示不尊重，0表示尊重
    vector<int> respect(100005);
    // children是一个邻接表结构，每个节点保存一个子节点集合(set)
    vector<set<int>> children(100005);
    
    // 标记根节点的编号
    int root = -1;
    
    // 遍历输入，逐个处理每个节点的信息
    for(int i = 1; i <= n; i++) {
        int p, c;
        cin >> p >> c; // p 是当前节点 i 的父节点，c 是它的尊重状态
        
        // 存储当前节点的父节点和尊重状态
        parent[i] = p;
        respect[i] = c;
        
        if(p == -1) { // 如果p是-1，说明该节点是根节点
            root = i;
        } else { // 否则将其添加到父节点的子节点集合中
            children[p].insert(i);
        }
    }
    
    // candidates集合用于维护所有当前可以删除的节点候选
    set<int> candidates;
    
    // 初始化candidates：遍历所有节点，检查是否符合删除条件
    for(int i = 1; i <= n; i++) {
        // 跳过根节点，只处理那些不尊重父节点的节点
        if(i != root && respect[i] == 1) {
            int p = parent[i]; // 当前节点的父节点
            
            // 检查当前节点的所有子节点是否都不尊重它
            bool canDelete = true;
            for(int child : children[i]) {
                if(respect[child] == 0) { // 只要有一个子节点尊重它，就不满足删除条件
                    canDelete = false;
                    break;
                }
            }
            
            // 如果满足删除条件，加入候选集合
            if(canDelete) {
                candidates.insert(i);
            }
        }
    }
    
    // 如果没有可删除节点，直接输出 -1 并结束程序
    if(candidates.empty()) {
        cout << -1 << endl;
        return 0;
    }
    
    // 处理删除过程
    while(!candidates.empty()) {
        // 取出编号最小的可删除节点
        int v = *candidates.begin();
        candidates.erase(candidates.begin());
        
        // 输出当前被删除的节点
        cout << v << " ";
        
        // 记录当前节点的父节点，并标记为已删除（通过设为-2）
        int p = parent[v];
        parent[v] = -2;
        
        // 将v的子节点连接到p上
        for(int child : children[v]) {
            // 确保child确实是v的直接子节点
            if(parent[child] == v) {
                parent[child] = p; // 更新子节点的父节点为v的父节点
                children[p].insert(child); // 将child添加到p的子节点集合中
                
                // 检查child现在是否符合删除条件
                if(respect[child] == 1) {
                    bool canDeleteChild = true;
                    for(int grandChild : children[child]) {
                        if(respect[grandChild] == 0) {
                            canDeleteChild = false;
                            break;
                        }
                    }
                    
                    // 如果child符合删除条件且不在候选集合中，则加入
                    if(canDeleteChild && candidates.find(child) == candidates.end()) {
                        candidates.insert(child);
                    }
                }
            }
        }
        
        // 检查p是否符合删除条件（即v的父节点是否也变成可删除状态）
        if(respect[p] == 1 && p != root) {
            bool canDeleteP = true;
            for(int child : children[p]) {
                if(respect[child] == 0) {
                    canDeleteP = false;
                    break;
                }
            }
            
            // 如果p符合删除条件且不在候选集合中，则加入
            if(canDeleteP && candidates.find(p) == candidates.end()) {
                candidates.insert(p);
            }
        }
        
        // 从p的子节点集合中移除v
        children[p].erase(v);
    }
    
    // 输出结束后换行
    cout << endl;
    
    // 主函数返回
    return 0;
}